﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DiscoveryLogic.Common.Utilities.OpenXml;
using System.IO;
using DiscoveryLogic.Common.Utilities;
using System.Data;
using DiscoveryLogic.Analytics.DataObjects.Networks;
using DiscoveryLogic.Analytics.DataObjects;
using DiscoveryLogic.Analytics.BusinessLogic;
using MessageBox=System.Windows.Forms.MessageBox;

namespace DiscoveryLogic.Analytics.Modules.DataImport
{
    /// <summary>
    /// Interaction logic for ImportCustomData.xaml
    /// </summary>
    public partial class ImportCustomData : UserControl
    {
        public ImportCustomData()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.cboEntityTypeField.Items.Clear();
            foreach (EntityType entityType in Enum.GetValues(typeof(EntityType)))
            {
                this.cboEntityTypeField.Items.Add(entityType.ToString());
            }
        }

        private void btnBrowse_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.OpenFileDialog dlg = new System.Windows.Forms.OpenFileDialog();
            dlg.Filter = "Excel files(*.xlsx)|*.xlsx|All files(*.*)|*.*";
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.txtFilePath.Text = dlg.FileName;
                List<string> worksheets = ExcelReader.GetWorksheetNames(dlg.FileName);
                this.cboWorksheet1.Items.Clear();
                this.cboWorksheet2.Items.Clear();
                foreach (string sheetName in worksheets)
                {
                    this.cboWorksheet1.Items.Add(sheetName);
                    this.cboWorksheet2.Items.Add(sheetName);
                }
            }
        }

        private void cboWorksheet1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.cboWorksheet1.SelectedIndex >= 0 && !string.IsNullOrEmpty(this.txtFilePath.Text))
            {
                if (!File.Exists(this.txtFilePath.Text))
                {
                    System.Windows.Forms.MessageBox.Show("File path does not exist");
                    return;
                }
                List<string> colHeaders = ExcelReader.ReadColumnHeaders(this.txtFilePath.Text, this.cboWorksheet1.SelectedItem.ToString());
                this.cboEntityIDField.Items.Clear();
                this.cboEntityNameField.Items.Clear();
                this.cboEntitySizeField.Items.Clear();
                foreach (string header in colHeaders)
                {
                    this.cboEntityIDField.Items.Add(header);
                    this.cboEntityNameField.Items.Add(header);
                    this.cboEntitySizeField.Items.Add(header);
                }
            }
        }

        private void cboWorksheet2_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.cboWorksheet2.SelectedIndex >= 0 && !string.IsNullOrEmpty(this.txtFilePath.Text))
            {
                if (!File.Exists(this.txtFilePath.Text))
                {
                    System.Windows.Forms.MessageBox.Show("Unable to find file path");
                    return;
                }
                List<string> colHeaders = ExcelReader.ReadColumnHeaders(this.txtFilePath.Text, this.cboWorksheet2.SelectedItem.ToString());
                this.cboFromEntityID.Items.Clear();
                this.cboToEntityID.Items.Clear();
                this.cboDistanceField.Items.Clear();
                this.cboAggregate.Items.Clear();
                foreach (string header in colHeaders)
                {
                    this.cboFromEntityID.Items.Add(header);
                    this.cboToEntityID.Items.Add(header);
                    this.cboDistanceField.Items.Add(header);
                    this.cboAggregate.Items.Add(header);
                }
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            if (this.Parent is Window)
                ((Window)this.Parent).Close();
        }

        private void btnOK_Click(object sender, RoutedEventArgs e)
        {
            double minLen = double.Parse(ConfigurationManager.AppSettings.Get("MinEdgeLength"));
            double maxLen = double.Parse(ConfigurationManager.AppSettings.Get("MaxEdgeLength"));
            try
            {
                if (this.cboWorksheet1.SelectedIndex < 0)
                {
                    System.Windows.Forms.MessageBox.Show("Select worksheet containing vertices");
                    return;
                }
                if (this.cboEntityTypeField.SelectedIndex < 0 ||
                    this.cboEntityIDField.SelectedIndex < 0 ||
                    this.cboEntityNameField.SelectedIndex < 0 ||
                    this.cboEntitySizeField.SelectedIndex < 0)
                {
                    System.Windows.Forms.MessageBox.Show("Select field(s) containing vertice attributes");
                    return;
                }
                if (this.cboWorksheet2.SelectedIndex < 0)
                {
                    System.Windows.Forms.MessageBox.Show("Select worksheet containing edges");
                    return;
                }
                if (this.cboFromEntityID.SelectedIndex < 0 ||
                    this.cboToEntityID.SelectedIndex < 0 ||
                    (this.cboDistanceField.SelectedIndex < 0 &&
                    this.cboAggregate.SelectedIndex < 0))
                {
                    System.Windows.Forms.MessageBox.Show("Select field(s) for edge attributes");
                    return;
                }

                DataTable dtVertices = ExcelReader.ReadTable(this.txtFilePath.Text, this.cboWorksheet1.SelectedItem.ToString());
                Dictionary<string, EntityBase> entities = new Dictionary<string, EntityBase>();
                foreach (DataRow dr in dtVertices.Rows)
                {
                    MiscEntity entity = new MiscEntity();
                    entity.EntityID = dr[this.cboEntityIDField.Text].ToString();
                    entity.EntityName = dr[this.cboEntityNameField.Text].ToString();
                    entities.Add(entity.EntityID, entity);
                }

                DataTable dtEdges = ExcelReader.ReadTable(this.txtFilePath.Text, this.cboWorksheet2.SelectedItem.ToString());
                List<Link> links = new List<Link>();
                double minDistance = double.PositiveInfinity;
                double maxDistance = 0;
                foreach (DataRow dr in dtEdges.Rows)
                {
                    double distance = 1.0;
                    if (this.cboDistanceField.SelectedIndex >= 0)
                        distance = double.Parse(dr[this.cboDistanceField.Text].ToString());
                    if(distance>maxDistance)
                        maxDistance = distance;
                    if(distance < minDistance)
                        minDistance = distance;
                }
                foreach (DataRow dr in dtEdges.Rows)
                {
                    string fromID = dr[this.cboFromEntityID.Text].ToString();
                    string toID = dr[this.cboToEntityID.Text].ToString();
                    double distance = 1.0;
                    if (this.cboDistanceField.SelectedIndex >= 0)
                        distance = double.Parse(dr[this.cboDistanceField.Text].ToString());
                    if (maxDistance > minDistance)
                    {
                        double scale = (double)(maxDistance - distance) / (maxDistance - minDistance);
                        distance = (maxLen - minLen)*scale + minLen;
                    }
                    int aggregate = 1;
                    if (this.cboAggregate.SelectedIndex >= 0)
                        aggregate = int.Parse(dr[this.cboAggregate.Text].ToString());
                    //if(aggregate>1)
                    //    distance = distance/aggregate;
                    Link link = new Link(
                        typeof (MiscEntity), typeof (MiscEntity),
                        fromID, toID, distance, aggregate, LinkType.Citation, false);
                    links.Add(link);
                }

                Network network = new Network(
                    this.txtNetworkName.Text, entities.Values.ToList(), links);

                network.Save();
                MyData.ReadAllNetworks();

                if (this.Parent is Window)
                    ((Window) this.Parent).Close();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}
